﻿using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Reflection;
using VitCode.Castle.Entities;
using VitCode.Castle.Helper;
using VitCode.ObjectResolutionHelper;

namespace Demo.History.Entities
{
    /// <summary>
    /// 历史记录基类
    /// </summary>
    public abstract class BaseHistoryEntity
    {
        private ObjectBuildHelper objBuilderHlp = new ObjectBuildHelper();
        

                        
        protected Guid m_HId;
        /// <summary>
        /// 数据唯一标识
        /// </summary>
        [OrMemo("历史数据唯一标识")]
        public virtual Guid HId
        {
            get { return m_HId; }
            set { m_HId = value; }
        }

        protected int m_HVersionId;
        /// <summary>
        /// 版本ID号,这里用Int型能更加明确版本产生的先后
        /// </summary>
        [OrMemo("版本号")]
        public virtual int HVersionId
        {
            get { return m_HVersionId; }
            set { m_HVersionId = value; }
        }

        protected Guid m_HParentId;
        /// <summary>
        /// 上一版本历史记录ID
        /// </summary>
        [OrMemo("上一版历史记录ID")]
        public virtual Guid HParentId
        {
            get { return m_HParentId; }
            set { m_HParentId = value; }
        }

        protected bool m_HIsLast;
        /// <summary>
        /// 是否最新
        /// </summary>
        [OrMemo("是否最新")]
        public virtual bool HIsLast
        {
            get { return m_HIsLast; }
            set { m_HIsLast = value; }
        }

        protected Guid m_HBaseObjectId;
        /// <summary>
        /// 记录对应的主体对象ID
        /// </summary>
        [OrMemo("记录对应的主体对象ID")]
        public virtual Guid HBaseObjectId
        {
            get { return m_HBaseObjectId; }
            set { m_HBaseObjectId = value; }
        }

        protected string m_HisMemo;
        /// <summary>
        /// 历史备注(历史记录级)
        /// </summary>
        [OrMemo("历史备注")]
        public virtual string HisMemo
        {
            get { return m_HisMemo; }
            set { m_HisMemo = value; }
        }

        protected string m_Memo;
        /// <summary>
        /// 备注
        /// </summary>
        [OrMemo("备注")]
        public virtual string Memo
        {
            get { return m_Memo; }
            set { m_Memo = value; }
        }

        protected bool m_IsLogicDelete;
        /// <summary>
        /// 逻辑删除的标记
        /// </summary>
        [OrMemo("逻辑删除的标记")]
        public virtual bool IsLogicDelete
        {
            get { return m_IsLogicDelete; }
            set { m_IsLogicDelete = value; }
        }

        protected string m_KeyWord;
        /// <summary>
        /// 关键字(以","分格)
        /// </summary>
        [OrMemo("关键字")]
        public virtual string KeyWord
        {
            get { return m_KeyWord; }
            set { m_KeyWord = value; }
        }

        

        public static StringCollection GetNotCompareProNames(object obj)
        {
            var scNotCompareProNames = new StringCollection();

            if (obj is BaseEntity)
                scNotCompareProNames = ((BaseEntity) obj).GetNotCompareHisProNames();

            return scNotCompareProNames;
        }

        private static object GetChildObjProVal(PropertyInfo hisPro,object baseObj)
        {
            var ss = hisPro.Name.Split(HistoryKeyInfo.PRO_FG);
            if (ss.Length == 2)
            {
                var cObjProName = ss[0];
                var cObjKeyProName = ss[1];
                var proInfo = baseObj.GetType().GetProperty(cObjProName);
                if (proInfo != null)
                {
                    var cObjProInfo = proInfo.PropertyType.GetProperty(cObjKeyProName);
                    var proVal = proInfo.GetValue(baseObj, null);

                    if (cObjProInfo != null)
                    {
                        object cObjProVal=null;
                        if (proVal == null)
                        {
                            if (cObjProInfo.PropertyType == typeof (Guid))
                                cObjProVal = Guid.Empty;
                            else if (cObjProInfo.PropertyType == typeof (double)
                                     || cObjProInfo.PropertyType == typeof (Single)
                                     || cObjProInfo.PropertyType == typeof (int)
                                     || cObjProInfo.PropertyType == typeof (Int16)
                                     || cObjProInfo.PropertyType == typeof (Int64))
                                cObjProVal = 0;
                        }
                        else
                        cObjProVal = cObjProInfo.GetValue(proVal, null);
                        return cObjProVal;
                    }
                    
                    
                }
            }
            return null;
        }

        public static bool CompareToBaseHisObject(object obj, object hisObj,HisVersionInfo hisVerInfo)
        {
            if (obj == null)
                throw new ArgumentException("记录历史的对象不能为空");
            if (hisVerInfo == null)
                throw new ArgumentException("历史版本对象不能为空");
            if (hisVerInfo.WoInfoId != Guid.Empty)
                return false;
            PropertyInfo[] ps = hisObj.GetType().GetProperties();
            StringCollection scNotCompareProNames = GetNotCompareProNames(obj);
            if (ps != null)
            {
                foreach (PropertyInfo hisPro in ps)
                {
                    if (scNotCompareProNames.Contains(hisPro.Name))
                        continue;
                    object hisProVal = hisPro.GetValue(hisObj, null);
                    PropertyInfo objPro = obj.GetType().GetProperty(hisPro.Name);
                    if (objPro != null)//找得到存在与主对象一样的属性
                    {
                        object proVal = objPro.GetValue(obj, null);
                        if ((hisProVal == null && proVal != null) || (hisProVal != null && proVal == null))
                            return false;
                        if (hisProVal != null  && !hisProVal.Equals(proVal))
                            return false;
                    }
                    else
                    {
                        var ss = hisPro.Name.Split(HistoryKeyInfo.PRO_FG);
                        if(ss.Length == 2)
                        {
                            if (scNotCompareProNames.Contains(ss[0]))
                                continue;
                            object cObjProVal = GetChildObjProVal(hisPro, obj);
                            if ((hisProVal != null) && !hisProVal.Equals(cObjProVal))
                                return false;
                        }
                    }
                }
            }
            return true;
        }

        public virtual void CreateHisRecord(object obj,int versionId,string hisMemo)
        {
            if (obj == null)
                new ArgumentException("主体对象不能为空,否则无法创建历史对象");
            PropertyInfo[] ps = GetType().GetProperties();
            if (ps.Length==0)
            {
                return;
            }
            var scNotCompareProNames = GetNotCompareProNames(obj);
            foreach (PropertyInfo hisPro in ps)
            {
                if (scNotCompareProNames.Contains(hisPro.Name))
                    continue;
                PropertyInfo basePro = obj.GetType().GetProperty(hisPro.Name);
                if (basePro != null)
                {
                    object objProVal = basePro.GetValue(obj, null);
                    hisPro.SetValue(this,objProVal , null);
                }
                else
                {
                    var ss = hisPro.Name.Split(HistoryKeyInfo.PRO_FG);
                    if (ss.Length == 2)
                    {
                        if (scNotCompareProNames.Contains(ss[0]))
                            continue;
                        var cObjProVal = GetChildObjProVal(hisPro, obj);
                        hisPro.SetValue(this, cObjProVal, null);
                    }
                }
            }

            object objBaseObjectId = objBuilderHlp.GetPropertyValue(HistoryKeyInfo.ID, obj);
            m_HBaseObjectId = (Guid)objBaseObjectId;
            m_HVersionId = versionId;
            m_HIsLast = true;
        }
    }
}
